import java.io.*;
import java.net.*;
import java.util.LinkedList;

interface MsgListener{
    void MsgRecvd(String msg);
}

class Server implements MsgListener{
    public static int PORT = 8080;
    PrintWriter out;

    LinkedList<MsgListener> connectingListeners = new LinkedList<>();

    public void MsgRecvd(String msg) {
        connectingListeners.forEach(item->item.MsgRecvd(msg));
    }
    public void addListener(MsgListener l){
        connectingListeners.add(l);
    }

    void run() throws IOException{
        ServerSocket serverSocket = new ServerSocket(PORT);
        System.out.printf("Starting at %d\n",PORT);
        try (serverSocket) {
            while(true) {
                Socket socket = serverSocket.accept();
                System.out.printf("Connected to %s!\n",socket.getInetAddress());
                out = new PrintWriter(
                    new OutputStreamWriter(
                        socket.getOutputStream()),true);// or it won't echo back
                out.println("Connected to Server!");
                Client client = new Client(socket, this);
                addListener(client);
            }
        } catch (IOException e){}
    }
    public static void main(String[] args) {
        Server server = new Server();
        try{
            server.run();
        }catch(IOException e){}
    }
}

class Client extends Thread implements MsgListener{
    final Socket socket;
    MsgListener host;
    BufferedReader in;
    PrintWriter out;
    Client(Socket socket, MsgListener host){
        this.socket = socket;
        this.host = host;
        start();
    }
    public void MsgSending(String msg) {
        host.MsgRecvd(msg);
    }
    @Override
    public void MsgRecvd(String msg) {
        out.println(msg);
    }
    @Override
    public void run() {
        try (socket) {
            in = new BufferedReader(
                new InputStreamReader(
                    socket.getInputStream()));
            out = new PrintWriter(
                    new OutputStreamWriter(
                        socket.getOutputStream()) , true);
            String msg;
            while(null != (msg = in.readLine())){
                System.out.printf("From %s:%s\n", socket.getInetAddress(),msg);
                MsgSending(msg);
            }
            // close connection
        } catch (IOException e) {}
    }


}